import csv
import os

from tc_python.server import TCPython


def thermodynamic(elements, target_phase, thermodynamic_database, temp, B_diff_pot_range, C_diff_pot_range, stoichiometric=0):
    size = len(B_diff_pot_range)*len(C_diff_pot_range)
    x_B_ = [0]*size
    x_C_ = [0]*size
    Gm = [0]*size
    Ni_chem_pot_ = [0]*size
    B_TF_ = [0]*size
    BC_TF_ = [0]*size
    C_TF_ = [0]*size
    condition_mu_1 = 'mu('+elements[1]+')-mu('+elements[0]+')'
    condition_mu_2 = 'mu('+elements[2]+')-mu('+elements[0]+')'

    target_phase_name = target_phase
    if stoichiometric:
        target_phase_name = target_phase+"#2"
    name_x_1 = 'x('+target_phase_name+','+elements[1]+')'
    name_x_2 = 'x('+target_phase_name+','+elements[2]+')'
    name_gm = 'GM('+target_phase_name+')'
    name_mu = 'mu('+elements[0]+')'
    name_tf_11 = "TF("+target_phase_name+"," + \
        elements[1]+","+elements[1]+","+elements[0]+")"
    name_tf_12 = "TF("+target_phase_name+"," + \
        elements[1]+","+elements[2]+","+elements[0]+")"
    name_tf_22 = "TF("+target_phase_name+"," + \
        elements[2]+","+elements[2]+","+elements[0]+")"

    filename = "Thermodynamic_%s_%s_%s_%s_%.2fK_Raw.csv" % (
        elements[0], elements[1], elements[2], target_phase, temp)

    with TCPython() as session:
        session.set_cache_folder(os.path.basename(
            __file__) + "_cache")

        system = (session
                  .select_database_and_elements(thermodynamic_database, elements)
                  .deselect_phase("*")
                  .select_phase(target_phase)
                  .get_system()
                  )
        calc = (system
                .with_single_equilibrium_calculation()
                .set_condition("P", 101325)
                .set_condition("N", 1)
                .set_condition("T", temp)
                .disable_global_minimization()
                )

        count = 0
        raw_file = open(filename, mode='a', newline='')
        raw_writer = csv.writer(raw_file)
        raw_headers = ['count',
                       elements[1]+'_diff_pot', 'x_' +
                       elements[1]+'_'+target_phase,
                       elements[2]+'_diff_pot', 'x_' +
                       elements[2]+'_'+target_phase,
                       'Gm'+target_phase, elements[0] +
                       '_chem_pot_'+target_phase,
                       'TF'+elements[1]+elements[1]+'_'+target_phase,
                       'TF'+elements[1]+elements[2]+'_'+target_phase,
                       'TF'+elements[2]+elements[2]+'_'+target_phase]
        raw_writer.writerow(raw_headers)
        debug_counts = []

        for i in range(len(B_diff_pot_range)):
            for j in range(len(C_diff_pot_range)):
                (calc
                    .set_condition(condition_mu_1, B_diff_pot_range[i])
                    .set_condition(condition_mu_2, C_diff_pot_range[j])
                    .run_poly_command("SET_ALL_START_VALUES F")
                 )
                if stoichiometric:
                    (calc
                        .set_phase_to_suspended(target_phase+"#1")
                        .set_phase_to_entered(target_phase+"#2", 1)
                     )
                try:
                    results = calc.calculate()
                except Exception as e:
                    print(count)
                    debug_counts.append(count)
                    print(e)
                    x_B_[count] = 'NaN'
                    x_C_[count] = 'NaN'
                    Gm[count] = 'NaN'
                    Ni_chem_pot_[count] = 'NaN'
                    B_TF_[count] = 'NaN'
                    BC_TF_[count] = 'NaN'
                    C_TF_[count] = 'NaN'
                else:
                    x_B_[count] = results.get_value_of(name_x_1)
                    x_C_[count] = results.get_value_of(name_x_2)
                    Gm[count] = results.get_value_of(name_gm)
                    Ni_chem_pot_[count] = results.get_value_of(name_mu)
                    B_TF_[count] = results.get_value_of(name_tf_11)
                    BC_TF_[count] = results.get_value_of(name_tf_12)
                    C_TF_[count] = results.get_value_of(name_tf_22)
                finally:
                    data_array = [count,
                                  B_diff_pot_range[i], x_B_[count],
                                  C_diff_pot_range[j], x_C_[count],
                                  Gm[count], Ni_chem_pot_[count],
                                  B_TF_[count], BC_TF_[count], C_TF_[count]]
                    raw_writer.writerow(data_array)
                    count = count + 1
        raw_file.close()
    return filename
